装饰者模式
将原对象丢进装饰者中进行装饰,返回一个更丰富的对象。
装饰者模式偏向于继承通用对象或者借口,使更多对象都可以进行装饰。对象的实例是通过传入的参数实现。
1. 知识点
- 装饰者模式定义
- 装饰者模式类图
- 装饰者模式示例
- 装饰者模式应用
- 装饰者模式、适配器模式区别
装饰者模式(Decorator Pattern,有的也用 Wrapper Pattern)就是动态地把职责附加到已有对象上去,实现功能扩展。这种特性,使得装饰者模式提供了比继承更具有弹性的解决方案。
2. 类图
3. 示例代码
// 抽象类 Girl
abstract class Girl {
String description = "no particular";
public String getDescription(){
return description;
}
}
// 美国女孩
class AmericanGirl extends Girl {
public AmericanGirl() {
description = "+AmericanGirl";
}
}
// 国产妹子
class ChineseGirl extends Girl {
public ChineseGirl() {
description = "+ChineseGirl";
}
}
// 装饰者
abstract class GirlDecorator extends Girl {
public abstract String getDescription();
}
// 下面以美国女孩示例
// 给美国女孩加上金发
class GoldenHair extends GirlDecorator {
private Girl girl;
public GoldenHair(Girl g) {
girl = g;
}
@Override
public String getDescription() {
return girl.getDescription() + "+with golden hair";
}
}
// 加上身材高大的特性
class Tall extends GirlDecorator {
private Girl girl;
public Tall(Girl g) {
girl = g;
}
@Override
public String getDescription() {
return girl.getDescription() + "+is very tall";
}
}
// 检验一下
public class Test {
public static void main(String[] args) {
Girl g1 = new AmericanGirl();
System.out.println(g1.getDescription());
GoldenHair g2 = new GoldenHair(g1);
System.out.println(g2.getDescription());
Tall g3 = new Tall(g2);
System.out.println(g3.getDescription());
// 也可以一步到位
// Girl g = new Tall(new GoldenHair(new AmericanGirl()));
}
}
4. 应用
当需要动态地给一个对象添加功能,实现功能扩展的时候,就可以使用装饰者模式。
Java IO 类中有一个经典的装饰者模式应用, BufferedReader 装饰了 InputStreamReader。
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
InputStreamReader(InputStream in) - InputSteamReader 读取 bytes 字节内容,然后转换成 characters 流 输出。BufferedReader(Reader in) - 从 characters 流 中读取内容并缓存。
5. 装饰者模式、适配器模式区别
关于新职责:适配器也可以在转换时增加新的职责,但其主要目的并不在此;而装饰者模式主要目的,就是给被装饰者增加新职责用的。
关于原接口:适配器模式是用新接口来调用原接口,原接口对新系统来说是不可见或者说不可用的;而装饰者模式原封不动的使用原接口,系统对装饰的对象也通过原接口来完成使用。
关于其包裹的对象:适配器是知道被适配者的详细情况的(就是那个类或那个接口);而装饰者只知道其接口是什么,至于其具体类型(是基类还是其他派生类)只有在运行期间才知道。